package dm.ast.model.gen;

import dm.ast.*;
import dm.ast.model.gen.factory.BaseModelFactory;
import dm.ast.model.gen.factory.ComplexityModel;
import dm.ast.model.gen.factory.FromModelFactory;
import test.utility.Randomly;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 根据模板AST生成FROM子句
 */
public class FromGen extends ASTGenBase{
    @Override
    public DmASTNode gen(int astLevel, int wid_t, int dep_t) {
        int on_wid = Randomly.getInteger(1,wid_t);//从from的宽度中分给on一些宽度
        ComplexityModel model = FromModelFactory.fromModels(wid_t-on_wid , dep_t);

        DmFrom from = new DmFrom();
        from.setTargetWidt(wid_t);
        from.setTargetDept(dep_t);

        from.on_wid = on_wid;
        //在model中遍历comps
        //如果dep_t为1，那么表示是表名，如果dep_t不为1，那么表示是子查询
        for (int i = 0; i < model.count; i++) {
            if(model.comps[i].dep_t == 1){
                DmTable tab = new DmTable();
                if(Randomly.getBoolean()){
                    tab.subTabFlag = true;
                }
                from.addTable(tab);
            }else {
                SelectGen selGen = new SelectGen();
                DmSelect select = (DmSelect) selGen.gen(astLevel + 1 , model.comps[i].wid_t , model.comps[i].dep_t - 1); //使用子查询，深度要减1
                DmSubSelect subSel = new DmSubSelect(select);
                //解决from中子查询的别名设置问题
                //利用节点中的ast_level变量，表明了层次
                //subSel.setAlias(String.format("T_L%d_%d" , astLevel , globalState.getAliasIndex()));
                from.addTable(subSel);
            }
        }
        return from;
    }

    public static DmASTNode joingen(DmFrom from, int astLevel, BaseModelFactory baseModelFactory){
        if(baseModelFactory.testFlags[BaseModelFactory.FLAG_JOIN]){
            int on_wid_use = from.on_wid;
            from.joinlist = new ArrayList<>();
            //随即返回一种join连接方式，存入on.joinType
            for (int i = 0; i < from.getTablesCnt(); i++) {
                List<DmJoinType> joinTypes = new ArrayList<>(Arrays.asList(DmJoinType.values()));
                if(!baseModelFactory.testFlags[BaseModelFactory.FLAG_NATURALJOIN]){
                    joinTypes.remove(DmJoinType.NaturalJoin);
                }
                if(!baseModelFactory.testFlags[BaseModelFactory.FLAG_OUTERJOIN]){
                    joinTypes.remove(DmJoinType.OuterJoin);
                }

                DmJoinType r = Randomly.fromList(joinTypes);
                DmJoinExpression on = new DmJoinExpression();

                on.jointype = r;

                if(r == DmJoinType.NaturalJoin){
                    if(Randomly.getBoolean()){
                        on.using = new DmColumn();
                    }
                }

                if(r == DmJoinType.InnerJoin || r == DmJoinType.OuterJoin || r==DmJoinType.Join){
                    if(r==DmJoinType.OuterJoin && Randomly.getBoolean()){
                        on.rightOrleft = 1;
                    }
                    int t = 0;
                    if(on_wid_use != 0){
                        t=Randomly.getInteger(1,on_wid_use);
                        on_wid_use -= t;
                    }else {
                        t=1;
                    }
                    BoolExpressionGen boolGen = new BoolExpressionGen(baseModelFactory.testFlags);

                    boolGen.JoinBoolGen(astLevel,t-1,1,on);
                }
                from.joinlist.add(on);
            }
        }
        return from;
    }
}
